package com.wzr;

import com.wzr.comparetool.DBCompareMan;
import com.wzr.comparetool.DBReport;
import com.wzr.comparetool.FileUtil;
import com.wzr.comparetool.TableViewIgnore;
import com.wzr.jdbc.Database;
import com.wzr.jdbc.JdbcUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

@RestController
@EnableConfigurationProperties(Database.class)
@RequestMapping("/sqldbcompare")
public class CompareController {

	public static final String DB_REPORT = "DBReport";
	public static final String COMPARE_REPORT = "CompareReport";
	public static final String DB_REPORT_PATH = COMPARE_REPORT + File.separator + DB_REPORT;
	public static final String DB_COMPARE = "DBCompare";
	public static final String DB_COMPARE_PATH = COMPARE_REPORT + File.separator + DB_COMPARE;

	@Autowired
	Database database;

	@RequestMapping("/report-list")
	public HashMap<String, ArrayList<String>> respReportList() {
		// 扫描报告目录路径
//		String dbReportPath = DB_REPORT_PATH;
		// 扫描报告目录绝对路径
		String dbRPAbsolute = FileUtil.legitimizeFolderPath(FileUtil.getAppPath() + DB_REPORT_PATH);
		System.out.println(dbRPAbsolute);
		String[] dbReportStrs  = getReportList(dbRPAbsolute);
		ArrayList<String> dbReportList;
		if (null == dbReportStrs) {
			dbReportList = null;
		}
		else {
			dbReportList = new ArrayList<>();
			for (int i = 0; i < dbReportStrs.length; ++i) {
				dbReportList.add(dbReportStrs[i]);
			}
		}
		HashMap<String, ArrayList<String>> dbRLMap = new HashMap<>();
		dbRLMap.put("dbReportList", dbReportList);
		return dbRLMap;
	}

	@RequestMapping("/dbServer-info")
	public Map<String, String> respDBServerInfo() {
		HashMap<String, String> dbMap = new HashMap<>();
		dbMap.put("serverName", database.getServerName());
		dbMap.put("port", database.getPort().toString());
		dbMap.put("databaseName", database.getDatabaseName());
		dbMap.put("userName", database.getUserName());
		return dbMap;
	}

	@RequestMapping("/new-dbreport")
	public Map<String, String> respNewDBReport() {
		String dbReportPath = DB_REPORT_PATH; // 扫描报告目录路径
		String newDBReportFilename = newDBReport(dbReportPath);
		HashMap newDBRFMap = new HashMap<>();
		if (null == newDBReportFilename) {
			newDBRFMap.put("ret", "Fail");
			newDBRFMap.put("description", "数据库连接失败");
			return newDBRFMap;
		}
		newDBRFMap.put("ret", "Success");
		newDBRFMap.put("newDBReportFilename", newDBReportFilename);
		return newDBRFMap;
	}

	@RequestMapping("/compare-db")
	public Map<String, String> respCompareDB(HttpServletRequest req) {
		String firstCompareFilename = req.getParameter("firstCompareFile");
		String secondCompareFilename = req.getParameter("secondCompareFile");
		String compareFileDes = req.getParameter("compareFileDes");
		String compareResultStr = newDBCompareResult(DB_REPORT_PATH, DB_COMPARE_PATH,
			firstCompareFilename, secondCompareFilename, compareFileDes);
		HashMap<String, String> compareResultMap = new HashMap<>();
		compareResultMap.put("compareResult", compareResultStr);
		return compareResultMap;
	}

	/**
	 * 获取现有报告文件列表
	 * @param dbReportPath folder of comparing report files
	 */
	private String[] getReportList(String dbReportPath) {
		String[] fileNameList = FileUtil.getFileNameList(dbReportPath, ".txt");
		return fileNameList;
	}



	/**
	 * 生成新的表比对结果
	 *
	 * @param dbReportPath  扫描结果目录路径
	 * @param dbComparePath 比对结果目录路径
	 * @return 成功则返回对比结果字符串, 失败返回空串
	 */
	private String newDBCompareResult(String dbReportPath, String dbComparePath,
	                                  String firstReportFile, String secondReportFile,
	                                  String compareFileDes) {
		String dbRPAbsolute = FileUtil.getAppPath() + dbReportPath + File.separatorChar;
		ArrayList<String> txtList = FileUtil.readTxtLines(dbRPAbsolute + firstReportFile);
		DBReport firstDBReport = new DBReport(firstReportFile, JdbcUtil.TABLE_TITLE, JdbcUtil.TABLE_END,
			JdbcUtil.VIEW_TITLE, JdbcUtil.VIEW_END, txtList);
		txtList = FileUtil.readTxtLines(dbRPAbsolute + secondReportFile);
		DBReport secondDBReport = new DBReport(secondReportFile, JdbcUtil.TABLE_TITLE, JdbcUtil.TABLE_END,
			JdbcUtil.VIEW_TITLE, JdbcUtil.VIEW_END, txtList);

		// 生成文件名
		String sigleFilename = System.currentTimeMillis()
			+ ((compareFileDes == null || compareFileDes.isEmpty()) ? "" : ("-" + compareFileDes)) + ".txt";
		String dbCpAbsolute = FileUtil.legitimizeFolderPath(FileUtil.getAppPath() + dbComparePath);

		// 开始比对
		DBCompareMan dbCompareMan = new DBCompareMan(firstDBReport, secondDBReport, sigleFilename);
		String strDBCompareResult = dbCompareMan.compare();

		FileUtil.writeTxt(dbCpAbsolute, strDBCompareResult, sigleFilename);
		return strDBCompareResult;
	}

	@Value("${tvignore}")
	private String tvignore;

	/**
	 * 进行一次新的DB扫描, 并将结果写入文件
	 * 包括表和视图
	 * @param dbReportPath 扫描结果目录路径
	 * @return 返回扫描结果文件名, 数据库连接失败返回null
	 */
	private String newDBReport(String dbReportPath) {
		return this.newDBReport(dbReportPath, "");
	}
	/**
	 * 进行一次新的DB扫描, 并将结果写入文件
	 * 包括表和视图
	 * @param dbReportPath 扫描结果目录路径
	 * @param compareFileDes 文件描述信息, 用于生成文件名
	 * @return 返回扫描结果文件名, 数据库连接失败返回null
	 */
	private String newDBReport(String dbReportPath, String compareFileDes) {
		String serverName = database.getServerName();
		String userName = database.getUserName();
		String password = database.getPassword();
		String dataBaseName = database.getDatabaseName();
		int port = database.getPort();
		StringBuffer textContent = new StringBuffer();
		JdbcUtil jdbcUtil = new JdbcUtil(serverName, dataBaseName, port, userName, password);
		textContent.append("/* Server:   ").append(serverName).append(" */\n");
		textContent.append("/* Port:     ").append(port).append(" */\n");
		textContent.append("/* Database: ").append(dataBaseName).append(" */\n");
		textContent.append("/* Username: ").append(userName).append(" */\n");
		TableViewIgnore tvi = new TableViewIgnore("classpath:config/" + tvignore);

		String tableListString = jdbcUtil.getTableListString(tvi.getTableIgnoreList());
		if (tableListString.isEmpty()) {
			return null;
		}
		textContent.append(tableListString);
		textContent.append(jdbcUtil.getViewListString(tvi.getViewIgnoreList()));
//		System.out.println("扫描报告：" + "\n" + textContent);

		if (textContent.length() > 0) {
			// 生成文件名
			String sigleFilename = System.currentTimeMillis()
				+ ((compareFileDes == null || compareFileDes.isEmpty()) ? "" : ("-" + compareFileDes)) + ".txt";
			String dbRPAbsolute = FileUtil.legitimizeFolderPath(FileUtil.getAppPath() + dbReportPath);

			if (textContent.charAt(textContent.length() - 1) == '\n') {
				return FileUtil.writeTxt(dbRPAbsolute, textContent.substring(0, textContent.length() - 1)
					, sigleFilename);
			} else {
				return FileUtil.writeTxt(dbRPAbsolute, textContent.toString(), sigleFilename);
			}
		}
		return "";
	}

	/**
	 * 显示主菜单
	 */
	private static void printMainMenu() {
		System.out.println("请选择功能:");
		System.out.println("1.进行一次新的扫描");
		System.out.println("2.比对现有报告");
		System.out.println("3.查看现有报告文件列表");
		System.out.println("Q.退出");
		System.out.print("请输入:");
	}

	/**
	 * 打印数据库连接信息
	 */
	private void printDBConInfo() {
		String serverName = database.getServerName();
		String userName = database.getUserName();
		String dataBaseName = database.getDatabaseName();
		int port = database.getPort();
//		Properties properties = new Properties();
//		InputStream inputStream = Application.class.getResourceAsStream("config/DB.properties");
		try {
//			properties.load(inputStream);
//			serverName = properties.getProperty("serverName");
//			port = Integer.parseInt(properties.getProperty("port"));
//			dataBaseName = properties.getProperty("dataBaseName");
//			userName = properties.getProperty("userName");
			System.out.println("Database connection info: ");
			System.out.println("Server name: " + serverName);
			System.out.println("Service port: " + port);
			System.out.println("Database name: " + dataBaseName);
			System.out.println("User name: " + userName);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 取对比报告数量
	 *
	 * @return 成功返回对比报告数量, 失败返回 0
	 */
	private static int getDBCompareReportNumber(String dbReportPath) {
		String[] fileNameList = FileUtil.getFileNameList(dbReportPath, ".txt");
		if (null != fileNameList) {
			return fileNameList.length;
		}
		return 0;
	}

}
